package admin

import (
	"crypto/md5"
	"fmt"
	"go.getaway.adminspro.padmins.com/untils"
	"go.getaway.adminspro.padmins.com/untils/handler"
	"math/rand"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

func Index(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"admin_id": fmt.Sprintf("%v", c.Auth.Get("id")),
	}
	where, bindValue, limit, order, e := c.BusinessCommonQuery.Build()

	if e != nil {
		return nil, untils.BusinessErrorf(e.Error())
	}

	adminIds := []interface{}{}
	authRuleIds := []interface{}{}
	roleIds := []interface{}{}
	if params["admin_id"] != "" {
		roleIds = c.Auth.GetChildrenRoleIds(params["admin_id"], true)
		adminIds = c.Auth.GetChildrenAdminIdsByRoleIds(roleIds, params["admin_id"], true)
		authRuleIds = c.Auth.GetRoleIdsByAdminId(params["admin_id"])
	}

	if len(adminIds) > 0 {
		where += " and a.id in (?)"
		bindValue = append(bindValue, adminIds)
	}

	total, e := c.Db.Find(fmt.Sprintf("select count(distinct a.id) total from admin a "+
		"left join admin_role_access agc on agc.admin_id=a.id "+
		"where 1=1 %s", where), bindValue...)

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	rows, e := c.Db.Query(fmt.Sprintf("select a.* from admin a left join admin_role_access agc on agc.admin_id=a.id "+
		"where 1=1 %s group by a.id %s %s", where, order, limit), bindValue...)

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	if len(rows) > 0 {
		adminIds := untils.ArrayColumn(rows, "id")
		roleRows, e := c.Db.Query("select a.admin_id,g.* from admin_role_access a "+
			"join admin_role g on g.id=a.role_id "+
			"where admin_id in (?) and g.id in (?)", adminIds, roleIds)

		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		rolesMap := map[string][]map[string]interface{}{}
		for _, role := range roleRows {
			rolesMap[fmt.Sprintf("%v", role["admin_id"])] = append(rolesMap[fmt.Sprintf("%v", role["admin_id"])], role)
		}

		for _, row := range rows {
			c.ListFormat(list(), row)
			delete(row, "password")
			delete(row, "salt")
			delete(row, "token")
			row["role_id"] = ""
			row["role_text"] = ""
			row["disabled"] = 0
			if roles, ok := rolesMap[fmt.Sprintf("%v", row["id"])]; ok {
				ids := []string{}
				names := []string{}
				ids2 := []interface{}{}
				for _, role := range roles {
					ids = append(ids, fmt.Sprintf("%v", role["id"]))
					ids2 = append(ids2, role["id"])
					names = append(names, fmt.Sprintf("%v", role["name"]))
				}
				row["role_id"] = untils.Implode(",", ids)
				row["role_text"] = untils.Implode(",", names)
				if len(untils.ArrayIntersect(ids2, authRuleIds)) > 0 {
					row["disabled"] = 1
				}
			}
		}
	}

	return map[string]interface{}{
		"total": total["total"],
		"rows":  rows,
	}, nil
}

func List(c *handler.Handler) (map[string]interface{}, untils.Error) {
	return list(), nil
}

func list() map[string]interface{} {
	return map[string]interface{}{
		"status": map[string]interface{}{"1": "正常", "0": "禁用"},
	}
}

func Detail(c *handler.Handler) (map[string]interface{}, untils.Error) {

	params := map[string]string{
		"admin_id": fmt.Sprintf("%v", c.Auth.Get("id")),
		"id":       c.Request.Params("id", "").(string),
	}

	adminIds := []interface{}{}
	authRuleIds := []interface{}{}
	if params["admin_id"] != "" {
		adminIds = c.Auth.GetChildrenRoleAdminIds(params["admin_id"], true)
		authRuleIds = c.Auth.GetRoleIdsByAdminId(params["admin_id"])
	} else {
		adminIds = append(adminIds, params["admin_id"])
	}

	if params["id"] == "" {
		return nil, untils.BusinessErrorf("参数ID不能为空")
	}
	row, _ := c.Db.Find("select * from admin where id=? and id in (?)", params["id"], adminIds)

	if row == nil {
		return nil, untils.BusinessErrorf("未找到记录")
	}
	c.ListFormat(list(), row)

	roles, e := c.Db.Query("select a.admin_id,g.* from admin_role_access a "+
		"join admin_role g on g.id=a.role_id "+
		"where admin_id in (?)", params["id"])

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	ids := []string{}
	names := []string{}
	ids2 := []interface{}{}
	for _, role := range roles {
		ids = append(ids, fmt.Sprintf("%v", role["id"]))
		ids2 = append(ids2, role["id"])
		names = append(names, fmt.Sprintf("%v", role["name"]))
	}

	row["disabled"] = 0
	row["role_id"] = untils.Implode(",", ids)
	row["role_text"] = untils.Implode(",", names)
	if len(untils.ArrayIntersect(ids2, authRuleIds)) > 0 {
		row["disabled"] = 1
	}

	return map[string]interface{}{
		"row": row,
	}, nil
}

func Add(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"admin_id": fmt.Sprintf("%v", c.Auth.Get("id")),
		"email":    c.Request.ParamsToString("email", ""),
		"username": c.Request.ParamsToString("username", ""),
		"nickname": c.Request.ParamsToString("nickname", ""),
		"password": c.Request.ParamsToString("password", ""),
		"avatar":   c.Request.ParamsToString("avatar", ""),
		"status":   c.Request.ParamsToString("status", "1"),
	}

	roleIds := []interface{}{}
	if reflect.TypeOf(c.Request.Params("role_id")).Kind() == reflect.Slice {
		for _, roleId := range c.Request.Params("role_id").([]string) {
			if rid, e := strconv.Atoi(roleId); e == nil {
				roleIds = append(roleIds, int64(rid))
			}
		}
	} else {
		for _, roleId := range strings.Split(c.Request.ParamsToString("role_id", ""), ",") {
			if rid, e := strconv.Atoi(roleId); e == nil {
				roleIds = append(roleIds, int64(rid))
			}
		}
	}

	matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", params["email"])
	if matched != true {
		return nil, untils.BusinessErrorf("邮箱格式错误")
	}
	if params["nickname"] == "" {
		return nil, untils.BusinessErrorf("昵称不能为空")
	}
	matched, _ = regexp.MatchString("^[a-zA-Z][a-zA-Z0-9]{5,19}$", params["username"])
	if matched != true {
		return nil, untils.BusinessErrorf("账号只能以字母开头，长度为6-20")
	}
	if len(params["password"]) < 6 {
		return nil, untils.BusinessErrorf("密码不能小于6位")
	}
	if len(roleIds) == 0 {
		return nil, untils.BusinessErrorf("角色组不能为空")
	}
	if _, ok := list()["status"].(map[string]interface{})[params["status"]]; !ok {
		return nil, untils.BusinessErrorf("状态参数不合法")
	}

	hasEmail, _ := c.Db.Find("select * from admin where email=?", params["email"])

	if hasEmail != nil {
		return nil, untils.BusinessErrorf("邮箱已存在")
	}

	hasUsername, _ := c.Db.Find("select * from admin where username=?", params["username"])

	if hasUsername != nil {
		return nil, untils.BusinessErrorf("账号已存在")
	}

	if params["admin_id"] != "" {
		if len(untils.ArrayDiff(roleIds, c.Auth.GetChildrenRoleIds(params["admin_id"]))) > 0 {
			return nil, untils.BusinessErrorf("只能选择自己角色组下面的角色")
		}
	}

	salt := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%v%v", rand.Intn(99999-10000)+10000, untils.Date("Y-m-d H:i:s")))))[:6]
	password := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%x", md5.Sum([]byte(params["password"])))+salt)))
	id, e := c.Db.TransactionFunc(func() (interface{}, error) {
		Result, e := c.Db.Execute("insert into admin(email, username, nickname, password, salt, avatar, status, create_time, update_time)"+
			"values (?, ?, ?, ?, ?, ?, ?, ?, ?)", []interface{}{
			params["email"],
			params["username"],
			params["nickname"],
			password,
			salt,
			params["avatar"],
			params["status"],
			untils.Date("Y-m-d H:i:s"),
			untils.Date("Y-m-d H:i:s"),
		}...)

		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		id, e := Result.LastInsertId()

		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		for _, roleId := range roleIds {
			if roleId == "" || fmt.Sprintf("%v", roleId) == "0" {
				return nil, untils.BusinessErrorf("角色组参数不合法")
			}

			Result, e := c.Db.Execute("insert into admin_role_access(admin_id, role_id, update_time, create_time)"+
				"values(?,?,?,?)", id, roleId, untils.Date("Y-m-d H:i:s"), untils.Date("Y-m-d H:i:s"))

			if e != nil {
				return nil, untils.NewBusinessError(2000, e.Error())
			}

			rowCount, e := Result.RowsAffected()

			if e != nil {
				return nil, untils.NewBusinessError(2000, e.Error())
			}

			if rowCount <= 0 {
				return nil, untils.BusinessErrorf("添加管理员角色失败")
			}
		}

		return id, nil
	})

	if e != nil {
		return nil, untils.BusinessErrorf(e.Error())
	}

	return map[string]interface{}{
		"row": map[string]interface{}{
			"id": id,
		},
	}, nil
}

func Edit(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"admin_id": fmt.Sprintf("%v", c.Auth.Get("id")),
		"id":       c.Request.ParamsToString("id", ""),
		"email":    c.Request.ParamsToString("email", ""),
		"username": c.Request.ParamsToString("username", ""),
		"nickname": c.Request.ParamsToString("nickname", ""),
		"password": c.Request.ParamsToString("password", ""),
		"avatar":   c.Request.ParamsToString("avatar", ""),
		"status":   c.Request.ParamsToString("status", "1"),
	}

	aRoleId := []string{}
	if reflect.TypeOf(c.Request.Params("role_id")).Kind() == reflect.Slice {
		aRoleId = c.Request.Params("role_id").([]string)
	} else {
		aRoleId = strings.Split(c.Request.ParamsToString("role_id", ""), ",")
	}

	roleIds := []interface{}{}
	for _, roleId := range aRoleId {
		roleIds = append(roleIds, roleId)
	}
	matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", params["email"])
	if matched != true {
		return nil, untils.BusinessErrorf("邮箱格式错误")
	}
	if params["nickname"] == "" {
		return nil, untils.BusinessErrorf("昵称不能为空")
	}
	matched, _ = regexp.MatchString("^[a-zA-Z][a-zA-Z0-9]{5,19}$", params["username"])
	if matched != true {
		return nil, untils.BusinessErrorf("账号只能以字母开头，长度为6-20")
	}
	if params["password"] != "" && len(params["password"]) < 6 {
		return nil, untils.BusinessErrorf("密码不能小于6位")
	}
	if len(roleIds) == 0 {
		return nil, untils.BusinessErrorf("角色组不能为空")
	}
	if _, ok := list()["status"].(map[string]interface{})[params["status"]]; !ok {
		return nil, untils.BusinessErrorf("状态参数不合法")
	}

	adminIds := []interface{}{}
	if params["admin_id"] != "" {
		if params["admin_id"] == params["id"] {
			return nil, untils.BusinessErrorf("不能操作自己")
		}
		adminRoleIds := c.Auth.GetRoleIdsByAdminId(params["id"])
		authRoleIds := c.Auth.GetRoleIdsByAdminId(params["admin_id"])
		if len(untils.ArrayIntersect(adminRoleIds, authRoleIds)) > 0 {
			return nil, untils.BusinessErrorf("不能操作相同角色组的用户")
		}
		adminIds = c.Auth.GetChildrenRoleAdminIds(params["admin_id"], false)
		if !untils.InArray(params["id"], adminIds) {
			return nil, untils.BusinessErrorf("不能操作其他角色组的用户")
		}
		if len(untils.ArrayDiff(roleIds, c.Auth.GetChildrenRoleIds(params["admin_id"]))) > 0 {
			return nil, untils.BusinessErrorf("只能选择自己角色组下面的角色")
		}
	}

	row, e := c.Db.Find("select * from admin where id=? and id in (?)", params["id"], adminIds)

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	if row == nil {
		return nil, untils.BusinessErrorf("未找到记录")
	}

	if params["email"] != fmt.Sprintf("%v", row["email"]) {
		hasEmail, _ := c.Db.Find("select * from admin where email=?", params["email"])

		if hasEmail != nil {
			return nil, untils.BusinessErrorf("邮箱已存在")
		}
	}

	if params["username"] != fmt.Sprintf("%v", row["username"]) {
		hasUsername, _ := c.Db.Find("select * from admin where username=?", params["username"])

		if hasUsername != nil {
			return nil, untils.BusinessErrorf("账号已存在")
		}
	}

	if params["password"] != "" {
		row["salt"] = fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%v%v", rand.Intn(99999-10000)+10000, untils.Date("Y-m-d H:i:s")))))[:6]
		row["password"] = fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%x", md5.Sum([]byte(params["password"])))+row["salt"].(string))))
		row["token"] = ""
	}

	_, e = c.Db.TransactionFunc(func() (interface{}, error) {
		Result, e := c.Db.Execute("update admin set username=?, email=?, token=?, password=?,"+
			"salt=?, nickname=?, avatar=?, status=?, update_time=?, create_time=? where id=?", []interface{}{
			params["username"],
			params["email"],
			row["token"],
			row["password"],
			row["salt"],
			params["nickname"],
			params["avatar"],
			params["status"],
			untils.Date("Y-m-d H:i:s"),
			untils.Date("Y-m-d H:i:s"),
			row["id"],
		}...)

		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		rowCount, e := Result.RowsAffected()

		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		if rowCount <= 0 {
			return nil, untils.BusinessErrorf("操作失败")
		}

		hasRole, e := c.Db.Query("select role_id from admin_role_access where admin_id=?", row["id"])
		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		hasRoleIds := untils.ArrayColumn(hasRole, "role_id")

		addRoleIds := untils.ArrayDiff(roleIds, hasRoleIds)
		delRoleIds := untils.ArrayDiff(hasRoleIds, roleIds)
		if len(delRoleIds) > 0 {
			Result, e := c.Db.Execute("delete from admin_role_access where admin_id=? and role_id in (?)", row["id"], delRoleIds)
			if e != nil {
				return nil, untils.NewBusinessError(2000, e.Error())
			}

			rowCount, e := Result.RowsAffected()
			if e != nil {
				return nil, untils.NewBusinessError(2000, e.Error())
			}

			if rowCount <= 0 {
				return nil, untils.BusinessErrorf("操作失败")
			}
		}

		for _, roleId := range addRoleIds {
			Result, e := c.Db.Execute("insert into admin_role_access(admin_id, role_id, update_time, create_time)"+
				"values(?,?,?,?)", row["id"], roleId, untils.Date("Y-m-d H:i:s"), untils.Date("Y-m-d H:i:s"))

			if e != nil {
				return nil, untils.NewBusinessError(2000, e.Error())
			}

			rowCount, e := Result.RowsAffected()

			if e != nil {
				return nil, untils.NewBusinessError(2000, e.Error())
			}

			if rowCount <= 0 {
				return nil, untils.BusinessErrorf("添加管理员角色失败")
			}
		}

		return nil, nil
	})

	if e != nil {
		return nil, untils.BusinessErrorf(e.Error())
	}

	return map[string]interface{}{}, nil
}

func Del(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"admin_id": fmt.Sprintf("%v", c.Auth.Get("id")),
		"id":       c.Request.ParamsToString("id", ""),
	}

	ids := []interface{}{}
	for _, id := range strings.Split(params["id"], ",") {
		ids = append(ids, id)
	}
	adminIds := []interface{}{}
	authRoleIds := []interface{}{}
	if params["admin_id"] != "" {
		adminIds = c.Auth.GetChildrenRoleAdminIds(params["admin_id"], true)
		authRoleIds = c.Auth.GetRoleIdsByAdminId(params["admin_id"])
	} else {
		adminIds = append(adminIds, params["admin_id"])
	}

	if len(untils.ArrayDiff(ids, adminIds)) > 0 {
		return nil, untils.BusinessErrorf("不能操作其他角色组的用户")
	}

	has, e := c.Db.Find("select a.admin_id,g.* from admin_role_access a "+
		"join admin_role g on g.id=a.role_id "+
		"where admin_id in (?) and g.id in (?)", ids, authRoleIds)

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	if has != nil {
		return nil, untils.BusinessErrorf("不能删除跟自己相同角色的管理员")
	}

	c.Db.TransactionFunc(func() (interface{}, error) {
		Result, e := c.Db.Execute("delete from admin where id in (?)", ids)
		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		rowCount, e := Result.RowsAffected()
		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		if rowCount <= 0 {
			return nil, untils.BusinessErrorf("操作失败")
		}

		Result, e = c.Db.Execute("delete from admin_role_access where admin_id in (?)", ids)
		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		rowCount, e = Result.RowsAffected()
		if e != nil {
			return nil, untils.NewBusinessError(2000, e.Error())
		}

		if rowCount <= 0 {
			return nil, untils.BusinessErrorf("操作失败")
		}

		return nil, nil
	})

	return map[string]interface{}{}, nil
}

func Multi(c *handler.Handler) (map[string]interface{}, untils.Error) {
	params := map[string]string{
		"admin_id": fmt.Sprintf("%v", c.Auth.Get("id")),
		"id":       c.Request.ParamsToString("id", ""),
		"field":    c.Request.ParamsToString("field", ""),
		"value":    c.Request.ParamsToString("value", ""),
	}

	ids := []interface{}{}
	for _, id := range strings.Split(params["id"], ",") {
		ids = append(ids, id)
	}
	adminIds := []interface{}{}
	authRoleIds := []interface{}{}
	if params["admin_id"] != "" {
		adminIds = c.Auth.GetChildrenRoleAdminIds(params["admin_id"], true)
		authRoleIds = c.Auth.GetRoleIdsByAdminId(params["admin_id"])
	} else {
		adminIds = append(adminIds, params["admin_id"])
	}

	if len(untils.ArrayDiff(ids, adminIds)) > 0 {
		return nil, untils.BusinessErrorf("不能操作其他角色组的用户")
	}

	has, e := c.Db.Find("select a.admin_id,g.* from admin_role_access a "+
		"join admin_role g on g.id=a.role_id "+
		"where admin_id in (?) and g.id in (?)", ids, authRoleIds)

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	if has != nil {
		return nil, untils.BusinessErrorf("不能操作跟自己相同角色的管理员")
	}

	row, e := c.Db.Find("select * from admin where id in (?)", ids)

	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	if row == nil {
		return nil, untils.BusinessErrorf("未找到记录")
	}

	if _, ok := row[params["field"]]; !ok {
		return nil, untils.BusinessErrorf("操作字段不存在")
	}

	if values, ok := list()[params["field"]]; ok {
		if _, ok = values.(map[string]interface{})[params["value"]]; !ok {
			return nil, untils.BusinessErrorf("操作字段值不合法")
		}
	}

	Result, e := c.Db.Execute(fmt.Sprintf("update admin set %s=? where id in (?)", params["field"]), params["value"], ids)
	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	_, e = Result.RowsAffected()
	if e != nil {
		return nil, untils.NewBusinessError(2000, e.Error())
	}

	return map[string]interface{}{}, nil
}
